
include Table
class TableFrame < Wx::Frame
  attr_accessor :grid,:book,:tables
  def initialize par,id=-1,title=""
    super par,id,title,:size=>Wx::Size::new(800,600)
    setup_menu
    setup_toolbar
    @saved=nil
    @modify=nil
    @new_size=[99,26]
    @tables=-1
    @book = RBook.new
    @nb = Wx::AuiNotebook.new self,-1,Wx::DEFAULT_POSITION,Wx::DEFAULT_SIZE,Wx::AUI_NB_BOTTOM
    @row_eval = Wx::TextCtrl::new self,-1,"0",:size=>Wx::Size::new(20,25)
    @row_eval_body = Wx::TextCtrl::new self,-1,:size=>Wx::Size::new(690,25)

    self.set_sizer Wx::BoxSizer.new(Wx::VERTICAL)
  
    tools = Wx::BoxSizer::new(Wx::HORIZONTAL)
    b=Wx::Button::new self,1973,"Eval as row"
    [b,@row_eval,@row_eval_body].each {|w|
      tools.add w,0,0;}

    sizer.add tools
    sizer.add @nb,Wx::ALL|Wx::GROW,Wx::EXPAND
    new_sheet
    setup_events
    
    evt_size {|e|
      @nb.each_page do |page|
        s=@nb.size
        x,y=s.get_x,s.get_y
        x=x-15;y=y-50
        page.children[0].size=Wx::Size::new(x,y);end
      e.skip;};end

  def setup_toolbar
        tb = create_tool_bar(Wx::TB_HORIZONTAL | Wx::NO_BORDER | Wx::TB_FLAT | Wx::TB_TEXT)
        
        create_status_bar()
        tb.add_tool(10,"Exit", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_QUIT) )
        tb.add_separator()
        tb.add_tool(11,"New Book", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_NEW) )
        tb.add_tool(12,"Open Book", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_FILE_OPEN) )
        tb.add_separator()
        tb.add_tool(13,"Save Book", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_FILE_SAVE) )
        tb.add_tool(14,"Save As", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_FILE_SAVE_AS) )
        tb.add_separator()
        tb.add_tool(15,"New Sheet", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_ADD_BOOKMARK) )
        tb.add_tool(16,"Remove Sheet", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_CROSS_MARK) )
        tb.add_separator()
        tb.add_tool(17,"Run Macro", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_EXECUTABLE_FILE ) )

        tb.add_separator()
        tb.add_tool(18,"Help", 
                  Wx::ArtProvider::get_bitmap(Wx::ART_HELP_BOOK ) )

        tb.realize();end

  def do_save
    if @saved or @modify
      @book.write_book;
      @saved=true
      @modify = false
p 88
      do_title
p 99
    else
      do_save_as();end;end

  def do_save_as
    wildcard = "RTableBook (*.rts)|*.rts"
    dlg = Wx::FileDialog.new(self, "Choose a file", ENV['HOME'], "", wildcard, Wx::SAVE)
    if dlg.show_modal() == Wx::ID_OK
      paths = dlg.get_paths()
      file=paths[0]
      path=File.dirname(file)

      if file[file.length-5..file.length-1] != ".rts"
        file=file+'.rts';end

      File.basename(file) =~ /(.*).rts/
      name=$1
      @book.bname=name
      @book.fpath=path
      @saved=true
      @modify = false
      do_save;end;end

  def do_open
    wildcard = "RTableBook (*.rts)|*.rts|Excel (*.xls)|*.xls"
    dlg = Wx::FileDialog.new(self, "Choose a file", ENV['HOME']+"/rtable/MyTables", "", wildcard, Wx::OPEN | Wx::MULTIPLE)
    book=nil

    if dlg.show_modal() == Wx::ID_OK
      paths = dlg.get_paths()
      file=paths[0]
      case file
        when /.*\.xls/
          book=from_excel(file)[0]
        when /.*\.rts/
          book = fopen(file);end;end

    if book 
      @book=book
      ind=[]
      @nb.each_page {|page|
       i = @nb.get_page_index page
       ind << i;}

      ind.each_with_index {|i,ind|
       @nb.delete_page(i-ind);}
     
      do_from_file(book)
      @saved=true
      @modify=false;end;end
   
  def do_from_file(book)
    @tables = -1
    @book.tables.each {|t|
      Fixnum.set_table t
      @tables = @tables + 1
      f = Wx::ScrolledWindow::new @nb,-1
      grid = TableSheet.new( f , -1,self );
      grid.create_grid( @new_size[0] , @new_size[1] );	
      s=@nb.size
      x,y=s.get_x,s.get_y
      nx = x-15
      ny = y-50
      grid.size=Wx::Size::new(nx,ny);
      @nb.add_page f,"Sheet(#{@tables})"
      @curTable = grid
      grid.fill_from_rtable

      for r in 1.table.length[0]..@new_size[0]
        0.table.add
        for c in 0..@new_size[1]
          r.push "";end;end;}

    Fixnum.set_table(@book.tables[0]);
    @nb.set_selection(0);end

  def do_new
      @book = RBook::new
      ind=[]
      @nb.each_page {|page|
       i = @nb.get_page_index page
       ind << i;}

      ind.each_with_index {|i,ind|
       @nb.delete_page(i-ind);}
      @tables=-1
      @saved=nil
      @modify=false
      new_sheet;end

  def do_export(mode)
    case mode
      when :excel
        @book.to_excel
        file = [@book.write_excel]
      when :html
        file = @book.to_html;end
    Wx::message_box("Wrote #{mode.to_s} to file(s):\n\n#{file.join("\n")}");end

  def do_new_sheet
    new_sheet
    @nb.set_selection(@tables)
  end

  def do_remove_sheet
   if @nb.get_page_count >= 1
    @modify = true if @saved
    pa = @nb.get_page(@nb.get_selection)
    i = @nb.get_page_index(pa)
    t=pa.children[0].rtable
    t.book.tables.delete t
    @tables = @tables - 1
    @nb.delete_page i;end;end
  
  def do_exit
    if @saved and !@modify
      destroy()
    else
      Wx::message_box("File not saved!");end;end

  # FIXME: just sync the cells of RTable And Grid instead of reloading the RTable (speed)
  def do_commit_cell e
    if defined?(@for_change)
      if @for_change
        @modify = true if @saved
        do_title
        r,c,g = @for_change
        @for_change = nil
        v = g.get_cell_value r,c
        if v=~/^\=e\:(.*)/
          v=eval($1)
          g.set_cell_value(r,c,v.to_s);end
        r.set(v,c);p [r,v,c];end;end;end

  def do_edit_cell e
    r,c=e.get_row,e.get_col
    i = @nb.get_selection
    sw = @nb.get_page(i)
    g = sw.children[0]
    t = g.rtable
#     p [r,v,c]
    @for_change=[r,c,g];do_commit_cell(e);end

  def setup_events
    evt_grid_cell_change() { | event | do_edit_cell(event);event.skip }
#     evt_grid_select_cell() { | event | do_commit_cell(event);event.skip }
    evt_menu(1979) {|e| do_export(:excel)}
    evt_menu(1978) {|e| do_export(:html)}
    evt_menu(Wx::ID_NEW) {|e| do_new()}
    evt_menu(Wx::ID_OPEN) {|e| begin; do_open(); rescue => e;Wx::message_box("""#{e}
#{e.backtrace.join("\n")}
""");end}
    evt_menu(Wx::ID_ADD) {|e| do_new_sheet()}
    evt_menu(Wx::ID_REMOVE) {|e| begin; do_remove_sheet(); rescue => e;Wx::message_box("""
#{e}
#{e.backtrace.join("\n")}""");end;}
    evt_menu(Wx::ID_EXIT) {|e| do_exit()}
    evt_menu(Wx::ID_SAVE) {|e| do_save()}
    evt_menu(Wx::ID_SAVEAS) {|e| do_save_as()}
    evt_menu(Wx::ID_ABOUT) {|e| do_about()}
    evt_tool(10) {|e| do_exit }
    evt_tool(11) {|e| do_new }
    evt_tool(12) {|e| begin; do_open(); rescue => e;Wx::message_box("""#{e}
#{e.backtrace.join("\n")}
""");end}
    evt_tool(13) {|e| do_save }
    evt_tool(14) {|e| do_save_as }
    evt_tool(15) {|e| do_new_sheet }
    evt_tool(16) {|e| begin; do_remove_sheet(); rescue => e;Wx::message_box("""
#{e}
#{e.backtrace.join("\n")}""");end;}
    evt_tool(17) {|e| begin; do_macro(); rescue => e;Wx::message_box("""
#{e}
#{e.backtrace.join("\n")}""");end;}
    evt_tool(18) {|e| do_help() }
    evt_button(1973) {|e| do_as_row()}
    evt_auinotebook_page_changed(@nb.get_id) {|e| do_sheet_change()};end

  def do_help
    hc=Wx::HtmlHelpController.instance
    hc.add_book "help/help.hpc",1
    hc.display("overview");end

  def do_about()
    mess = <<-EOM
RTable-Front: version 0.01
(c) ppibburr (tulnor@linuxwaves.com)
license: GNU

ABOUT:
  Front end to the RTable Table and Spreadsheet API's
  Allows for dynamic data representaion from ruby
  File Format: .rts (RTable Sheet)
  Exports to HTML and Excel
  Loads from .rts and .xls (Excel Files)
    EOM
    Wx::message_box(mess);end

  def do_sheet_change()
    i = @nb.get_selection
    sw = @nb.get_page(i)
    g = sw.children[0]
    @curTable=g
    Fixnum.set_table(@book.tables[i])
    do_title();end
 
  def do_title
    i = @nb.get_selection
    page = @nb.get_page i
    sheet=@nb.get_page_text(i)
    saved = ""
    if @modify or !@saved
      saved = "modified ";end

    set_title("RTable-Front: #{saved}#{@book.bname} : #{sheet}");end

  def do_as_row
    begin
      $grid=@curTable
      r=@row_eval.value.to_i
      method = @row_eval_body.value
      eval("#{r}.#{method}")
      @curTable.fill_from_rtable
    rescue => e
      Wx::message_box("""
#{e}
#{e.backtrace}
      """);end;end

 

 def do_macro
        mexample=mopts=mdesc=writing=lines=doing=mname=nil
        wildcard = "RubyScript (*.rb)|*.rb"
        dlg = Wx::FileDialog.new(self, "Choose a file", Dir.getwd+"/macros", "", wildcard, Wx::OPEN | Wx::MULTIPLE)
    
        if dlg.show_modal() == Wx::ID_OK
         paths = dlg.get_paths()
         file=paths[0]
         mname=File.basename(file)
         lines = File.open(file,'r').readlines
         lines.each {|l|
          if l=~/^DESCRIBE\:/
            writing = true
            mdesc=""
            doing = :mdesc
          elsif l=~/^OPTIONS\:/
            writing=true
            mopts=""
            doing = :mopts
          elsif l =~ /^EXAMPLE\:/
            writing = true
            mexample=""
            doing = :mex
          elsif l =~ /^\:[A-Z]+/
            doing = nil
            writing = nil
          elsif writing
            case doing
              when :mex
                mexample = mexample + l
              when :mopts
                mopts = mopts + l
              when :mdesc
                mdesc = mdesc + l;end;end;}
        dlg = Wx::TextEntryDialog.new(self, "#{mdesc}\n\n#{mopts}\n\n#{mexample}", mname, "")
        dlg.set_value("Ruby is the best!")
        if dlg.show_modal() == Wx::ID_OK
           v=dlg.get_value().to_s
           file = "opts=#{v};"+"\n"+lines.join
           eval(file)
           @modify=true if @saved
           do_title
        end;end     
        return nil;end

  Id_ExportExcel = 1979
  Id_ExportHtml = 1978
  def setup_menu
    # File menu
    menuFile = Wx::Menu.new
    menuFile.append Wx::ID_NEW,"&New Book\tCtrl-N","Creates a RBook"
    menuFile.append Wx::ID_OPEN,"&Open Book\tCtrl-O","Loads a RBook from a .rts or .xls (Excel file)"
    menuFile.append_separator
    menuFile.append Wx::ID_SAVE,"&Save Book\tCtrl-S","Saves a RBook"
    menuFile.append Wx::ID_SAVEAS,"&Save Book As\tCtrl-E","Saves a RBook"
    menuFile.append_separator
    menuFile.append Wx::ID_EXIT,"E&xit\tCtrl-Q","Quits the program"

    menuBook = Wx::Menu.new
    menuBook.append Wx::ID_ADD,"&New Sheet\tAlt-N","Creates a new sheet in the book"
    menuBook.append Wx::ID_REMOVE,"&Remove Sheet\tAlt-R","Removes a sheet from the book"
    menuFile.append_separator
    menuBook.append Id_ExportExcel,"&Save as Excel File\tAlt-E","Saves the rbook as an excel file"
    menuBook.append Id_ExportHtml,"&Export to HTML\tAlt-H","Makes html files representing the rbook"

    # Help menu
    menuHelp = Wx::Menu.new
    menuHelp.append(Wx::ID_ABOUT,"&About\tCtrl-F1","Show program information")

    # the Menubar
    menuBar = Wx::MenuBar.new
    menuBar.append menuFile, "&File"
    menuBar.append menuBook, "&Book"
    menuBar.append menuHelp, "&Help"
    set_menu_bar menuBar

end

  def new_sheet
    @modify = true if @saved
    @tables = @tables + 1
    @book << RTable::new
    f = Wx::ScrolledWindow::new @nb,-1
    grid = TableSheet.new( f , -1,self );
    grid.create_grid( @new_size[0] , @new_size[1] );	
    s=@nb.size
    x,y=s.get_x-15,s.get_y-50
    grid.size = Wx::Size::new(x,y)
    @nb.add_page f,"Sheet(#{@tables})"
    @curTable = grid
    fill_blank_rtable
    grid.fill_from_rtable
    do_title();end

  def fill_blank_rtable
    table = @book.tables[@tables]
    Fixnum.set_table table
    for r in 0..@new_size[0]
      table.add
      for c in 0..@new_size[1]
        table.rows[r][:cols][c]=("");end;end;end;end


class TableSheet < Wx::Grid
  attr_accessor :rtable
  def initialize par,id,frame
    super par,id
    @rtable = frame.book.tables[frame.tables];end
  def fill_from_rtable
    ok=true
    eok=nil
    @rtable.rows.each_with_index do |row,r|
      row[:cols].each_with_index do |col,c|
         hash = eval("{#{display_cell(r,c)}}")
         eok=cell_prop(self,r,c,hash).to_s
         if eok =~ /\#ERR/
           ok=nil;end;end;end
    if !ok
      Wx::message_box("#{eok}");end;end;end

class TableApp < Wx::App
	def on_init
		@frame = TableFrame.new( nil , -1 , "RTable Front" );
		@frame.show();end;end

b = TableApp.new();
begin
b.main_loop
rescue
true
end
